package entity.lianxi.demo10;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SqlGenerate {
    /**
     * 基于 Bean 对象，生成查询所有字段的语句
     *
     * @param beanClass 实体对象（Bean）的 Class 对象
     * @return 查询所有字段的 SQL 语句
     */
    public static String generateSelect(Class<?> beanClass) {
        // select id,name from user
        StringBuilder sql = new StringBuilder("select ");

        // 获取实体对象所有的字段
        Field[] fields = beanClass.getDeclaredFields();
        for (Field field : fields) {
            // 把驼峰命名转换为数据规范命名
            sql.append(convertToSnake(field.getName())).append(",");
        }

        // 删除拼接最后一个字段后面的 ,
        sql.deleteCharAt(sql.length() - 1);
        sql.append(" from ");
        // 把驼峰命名转换为数据规范命名
        sql.append(convertToSnake(beanClass.getSimpleName()));
        return sql.toString();
    }

    /**
     * 方法重载 - 基于 Bean 对象，生成查询所有字段的语句，并且根据 Map 集合指定的参数拼接查询条件
     *
     * @param beanClass 实体对象的 Class 对象
     * @param cond      查询条件
     * @return 带条件且查询所有字段的SQL语句
     */
    public static String generateSelect(Class<?> beanClass, Map<String, Object> cond) {
        // 调用重载方法，获取查询所有字段的 SQL 语句
        StringBuilder sql = new StringBuilder(generateSelect(beanClass));

        if (cond == null && cond.size() == 0) {
            return sql.toString();
        }

        // where id=? and name=? and
        sql.append(" where ");

        for (Map.Entry<String, Object> entry : cond.entrySet()) {
            sql.append(entry.getKey()).append("=?").append(" and ");
        }

        return sql.substring(0, sql.length() - 5);
    }


    /**
     * 实现把驼峰命名的字符串转换为数据的命名规范，如：
     * xxxXxxXxx - xxx_xxx_xxx
     * XxxXxxXxx - xxx_xxx_xxx
     *
     * @param input 驼峰命名的字符串
     * @return 数据规范命名的字符串
     */
    public static String convertToSnake(String input) {
        // 使用正则表达式替换，将大写字母前插入下划线，并将字符串转换为小写
        return input.replaceAll("(?<!^)([A-Z])", "_$1").toLowerCase();
    }


    /**
     * 把蛇型命名转换为驼峰命名
     * xxx_xxx_xxx - xxxXxxXxx
     * xxx_xxx_xxx - XxxXxxXxx
     *
     * @param input 蛇型命名的字符串
     * @return 驼峰命名的字符串
     */
    public static String convertToCamel(String input) {
        // 使用正则表达式匹配下划线及其后的字母
        Pattern pattern = Pattern.compile("_([a-z])");
        Matcher matcher = pattern.matcher(input);
        StringBuffer sb = new StringBuffer();

        while (matcher.find()) {
            // 将下划线后的字母转换为大写
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        }
        matcher.appendTail(sb);

        return sb.toString();
    }


    /**
     * 根据 Bean 对象，生成对应的添加数据的 SQL
     *
     * @param beanClass Bean对象 - 与数据表对应
     * @return insert SQL
     */
    public static String generateInsert(Class<?> beanClass) {
        // insert into 表名(字段1,字段2,...) values (?,?,?,?)
        StringBuilder sql = new StringBuilder("insert into ");

        String tableName = convertToSnake(beanClass.getSimpleName());
        sql.append(tableName).append("(");

        // 循环遍历 Bean 对象中的所有字段 - 注意：Bean对象的字段与数据表的字段一一对应
        Field[] fields = beanClass.getDeclaredFields();
        for (Field field : fields) {
            sql.append(convertToSnake(field.getName())).append(",");
        }
        // 去除最后一个逗号
        sql.deleteCharAt(sql.length() - 1);

        sql.append(") values (");

        // 再次循环（只要循环次数），添加 ? 占位符
        for (int i = 0; i < fields.length; i++) {
            sql.append("?").append(",");
        }
        // 去除最后一个逗号
        sql.deleteCharAt(sql.length() - 1);
        sql.append(")");
        return sql.toString();
    }
}
